using UnityEngine;
using Watermelon;

public class TutorialController : MonoBehaviour, ISaveController
{
    private const string SAVE_UNIQUE_IDENTIFIER = "tutorial";

    [SerializeField] GameObject arrowPrefab;
    [SerializeField] TutorialStage defaultTutorialStage = TutorialStage.PickFirstAnimal;

    public string UniqueSaveName => SAVE_UNIQUE_IDENTIFIER;
       
    private static TutorialStage currentTutorialStage = TutorialStage.None;
    public static TutorialStage CurrentTutorialStage => currentTutorialStage;

    // Arrow
    private static Pool arrowPool;

    // Events
    public static OnTutorialStageCompletedCallback OnTutorialStageCompleted;

    public static OnZoneOpenedCallback OnZoneOpenedEvent;
    public static OnAnimalPickedCallback OnAnimalPickedEvent;
    public static OnAnimalPlacedOnTableCallback OnAnimalPlacedOnTableEvent;
    public static OnItemPickedCallback OnItemPickedEvent;
    public static OnAnimalCuredCallback OnAnimalCuredEvent;
    public static OnMoneyPickedCallback OnMoneyPickedEvent;
    public static OnTableUnlockedCallback OnTableUnlockedEvent;
    public static OnTableZoneUnlockedCallback OnTableZoneUnlockedEvent;
    public static OnNurseHiredCallback OnNurseHiredEvent;

    public void Initialise()
    {
        // Create arrow pool
        arrowPool = new Pool(new PoolSettings(arrowPrefab.name, arrowPrefab, 1, true));

        // Register save object
        SaveController.RegisterSaveObject(this);
    }

    [Button("Finish Tutorial")]
    public void FinishTutorial()
    {
        EnableTutorial(TutorialStage.Done);
    }

    public static void EnableTutorial(TutorialStage tutorialStage)
    {
        // Store previous stage
        TutorialStage previousStage = currentTutorialStage;

        // Invoke complete stage method
        OnStageCompleted(currentTutorialStage);

        // Rewrite stage
        currentTutorialStage = tutorialStage;

        // Invoke stage event
        OnTutorialStageCompleted?.Invoke(tutorialStage, previousStage);

        SaveController.MarkAsSaveIsRequired();
    }

    private static void OnStageCompleted(TutorialStage tutorialStage)
    {

    }

    public static TutorialArrowBehaviour CreateTutorialArrow(Vector3 position)
    {
        GameObject arrowObject = arrowPool.GetPooledObject();
        arrowObject.transform.position = position;
        arrowObject.transform.rotation = Quaternion.identity;

        TutorialArrowBehaviour tutorialArrowBehaviour = arrowObject.GetComponent<TutorialArrowBehaviour>();
        tutorialArrowBehaviour.Activate();

        return tutorialArrowBehaviour;
    }

    #region Callback
    public static void OnZoneOpened(Zone zone)
    {
        OnZoneOpenedEvent?.Invoke(zone);
    } 

    public static void OnAnimalPicked(AnimalBehaviour animalBehaviour)
    {
        OnAnimalPickedEvent?.Invoke(animalBehaviour);
    }

    public static void OnAnimalPlacedOnTable(AnimalBehaviour animalBehaviour, TableBehaviour tableBehaviour)
    {
        OnAnimalPlacedOnTableEvent?.Invoke(animalBehaviour, tableBehaviour);
    }

    public static void OnAnimalCured(AnimalBehaviour animalBehaviour)
    {
        OnAnimalCuredEvent?.Invoke(animalBehaviour);
    }

    public static void OnItemPicked(Item item)
    {
        OnItemPickedEvent?.Invoke(item);
    }

    public static void OnMoneyPicked()
    {
        OnMoneyPickedEvent?.Invoke();
    }

    public static void OnTableUnlocked(TableBehaviour tableBehaviour)
    {
        OnTableUnlockedEvent?.Invoke(tableBehaviour);
    }

    public static void OnTableZoneUnlocked(TableZoneBehaviour tableZoneBehaviour)
    {
        OnTableZoneUnlockedEvent?.Invoke(tableZoneBehaviour);
    }

    public static void OnNurseHired()
    {
        OnNurseHiredEvent?.Invoke();
    }
    #endregion

    #region Load/Save
    public void Load(ISaveObject saveObject)
    {
        // Check if save exists
        if (saveObject != null)
        {
            // Change save type
            TutorialSave tutorialSave = (TutorialSave)saveObject;
            if (tutorialSave != null)
            {
                if(tutorialSave.TutorialStage != TutorialStage.None)
                {
                    EnableTutorial(tutorialSave.TutorialStage);
                }
                else
                {
                    EnableTutorial(defaultTutorialStage);
                }
            }
            else
            {
                EnableTutorial(defaultTutorialStage);
            }
        }
        else
        {
            EnableTutorial(defaultTutorialStage);
        }
    }

    public ISaveObject Save()
    {
        return new TutorialSave(currentTutorialStage);
    }
    #endregion

    public delegate void OnTutorialStageCompletedCallback(TutorialStage tutorialStage, TutorialStage previousStage);
    public delegate void OnZoneOpenedCallback(Zone zone);
    public delegate void OnAnimalPickedCallback(AnimalBehaviour animalBehaviour);
    public delegate void OnAnimalPlacedOnTableCallback(AnimalBehaviour animalBehaviour, TableBehaviour tableBehaviour);
    public delegate void OnItemPickedCallback(Item item);
    public delegate void OnAnimalCuredCallback(AnimalBehaviour animalBehaviour);
    public delegate void OnMoneyPickedCallback();
    public delegate void OnTableUnlockedCallback(TableBehaviour tableBehaviour);
    public delegate void OnTableZoneUnlockedCallback(TableZoneBehaviour tableZoneBehaviour);
    public delegate void OnNurseHiredCallback();
}
